﻿using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using JiveMessenger.CustomControls;
using JiveMessenger.Helpers;
using JiveMessenger.Interfaces;
using JiveMessenger.Models;
using JiveMessenger.Settings;
using JiveMessenger.User;
using JmShared;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace JiveMessenger.ViewModels
{
   public class ViewModelBaseChatControl:ViewModelBase
    {
        private DateTime LastMessageReceivedTime { get; set; }
        private object LockObject = new object();
        public ObservableCollection<MessageModel> Messages { get; set; }
        public ObservableCollection<EmoticonModel> CustomEmoticons { get; set; }
        public ObservableCollection<EmoticonModel> DefaultEmoticons { get; set; }
        public ObservableCollection<EmoticonModel> RecentlyUsedEmoticons { get; set; }

        private int _intputTextSelectionStart;
        public int InputTextSelectionStart
        {
            get { return _intputTextSelectionStart; }
            set
            {
                if (_intputTextSelectionStart != value)
                {
                    _intputTextSelectionStart = value;
                    RaisePropertyChanged("InputTextSelectionStart");
                }
            }
        }
        private int _inputTextSelectionLength;
        public int InputTextSelectionLength
        {
            get { return _inputTextSelectionLength; }
            set
            {
                if (_inputTextSelectionLength != value)
                {
                    _inputTextSelectionLength = value;
                    RaisePropertyChanged("InputTextSelectionLength");
                }
            }
        }

        private bool _showEmoticonPopup;

        public bool ShowEmoticonPopup
        {
            get { return _showEmoticonPopup; }
            set
            {


                if (_showEmoticonPopup != value)
                {
                    _showEmoticonPopup = value;
                    RaisePropertyChanged("ShowEmoticonPopup");
                }
            }
        }
        private string _inputText;
        public string InputText
        {
            get { return _inputText; }
            set
            {
                if (_inputText != value)
                {
                    _inputText = value;
                    RaisePropertyChanged("InputText");
                }
            }
        }

        public ViewModelBaseChatControl()
        {
            Messages = new ObservableCollection<MessageModel>();
            DefaultEmoticons = new ObservableCollection<EmoticonModel>();
            CustomEmoticons = new ObservableCollection<EmoticonModel>();
            RecentlyUsedEmoticons = new ObservableCollection<EmoticonModel>();
            DefaultEmoticons = CreateDefaultEmoticonList();


            Messenger.Default.Register<NotificationMessage>(this, msg =>
            {
                switch (msg.Notification)
                {
                    case "UpdateCustomEmoticons":
                        CreateCustomEmoticons();
                        break;
                }
            });
            CreateCustomEmoticons();
            UpdateRecentlyUsedEmoticonList();
        }


        internal void UpdateRecentlyUsedEmoticonList(EmoticonModel model = null)
        {
            if (model == null)
            {
                if (RecentlyUsedEmoticons == null)
                    RecentlyUsedEmoticons = new ObservableCollection<EmoticonModel>();
                foreach (var v in AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons)
                {
                    model = CustomEmoticons.FirstOrDefault(x => (string)x.EmoticonShortcut == v.Key);
                    if (!RecentlyUsedEmoticons.Contains(model))
                        RecentlyUsedEmoticons.Add(model);
                }
                foreach (var v in AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons)
                {
                    model = DefaultEmoticons.FirstOrDefault(x => ((string[])x.EmoticonShortcut).SequenceEqual(v.Key));
                    if (!RecentlyUsedEmoticons.Contains(model))
                        RecentlyUsedEmoticons.Add(model);
                }
            }
            else
            {
                if (!RecentlyUsedEmoticons.Contains(model))
                    RecentlyUsedEmoticons.Add(model);
            }
            if (RecentlyUsedEmoticons == null)
                return;
            var sortedList = RecentlyUsedEmoticons.ToList();
            sortedList.Sort((x, y) =>
            {
                int thisCount = 0;
                if (x.EmoticonType == EmoticonType.CustomEmoticon)
                    thisCount = AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons[(string)x.EmoticonShortcut];
                else if (x.EmoticonType == EmoticonType.DefaultEmoticon)
                {
                    var key = (string[])x.EmoticonShortcut;
                    thisCount = AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons.Where(z => z.Key.SequenceEqual(key)).First().Value;
                }

                int otherCount = 0;

                if (y.EmoticonType == EmoticonType.DefaultEmoticon)
                {
                    var key = (string[])y.EmoticonShortcut;
                    otherCount = AppSettings.AppSettingsInstance.RecentlyUsedDefaultEmoticons.Where(z => z.Key.SequenceEqual(key)).First().Value;
                }
                else if (y.EmoticonType == EmoticonType.CustomEmoticon)
                    otherCount = AppSettings.AppSettingsInstance.RecentlyUsedCustomEmoticons[(string)y.EmoticonShortcut];

                if (thisCount > otherCount)
                    return 0;
                else
                    return 1;

            });
            RecentlyUsedEmoticons = new ObservableCollection<EmoticonModel>(sortedList);
        }
        public void CreateCustomEmoticons()
        {
            CustomEmoticons = CreateCustomEmoticonList();
        }
        private ObservableCollection<EmoticonModel> CreateDefaultEmoticonList()
        {
            ObservableCollection<EmoticonModel> list = new ObservableCollection<EmoticonModel>();
            foreach (KeyValuePair<string[], string> kvp in StaticSettings.DefaultEmoticons)
            {
                list.Add(new EmoticonModel() { EmoticonShortcut = kvp.Key, EmoticonType = EmoticonType.DefaultEmoticon, EmoticonPath = "/Assets/DefaultEmoticons/" + kvp.Value });
            }
            return list;
        }
        private ObservableCollection<EmoticonModel> CreateCustomEmoticonList()
        {
            ObservableCollection<EmoticonModel> list = new ObservableCollection<EmoticonModel>();
            var ce = Client.Instance.GetEmoticons(Client.Instance.CurrentUserInfo, false, true, false);
            foreach (KeyValuePair<string, string> kvp in ce)
            {
                list.Add(new EmoticonModel() { EmoticonShortcut = kvp.Key, EmoticonType = EmoticonType.CustomEmoticon, EmoticonPath = kvp.Value });
            }
            return list;
        }



        public void DisplayMessage(ServerInfoMessage msg, bool doScroll=true)
        {
            DisplayMessage(msg.UserInfo, msg.Message, DateTime.Now, doScroll, true);
        }

        public void DisplayMessage(ChatMessage msg, bool doScroll = true)
        {
            bool isLastInBatch = msg.MessageQueueInfo == null || msg.MessageQueueInfo.QueuedMessageCount > 10 && (msg.MessageQueueInfo.QueuedMessageCount == msg.MessageQueueInfo.QueuedMessageNumber);
            DisplayMessage(msg.SenderInfo, msg.Message, msg.MessageRelayTime.GetValueOrDefault(), doScroll, isLastInBatch);
        }
        public void DisplayMessage(UserInfo user, string message, DateTime timestamp, bool doScroll = true, bool isLastInBatch = false)
        {
            if (user == null)
                throw new InvalidOperationException("UserInfo is null");
            if (String.IsNullOrEmpty(message))
                return;
            if (user.Color == null)
                user.Color = "#000000";

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                lock (LockObject)
                {
                    MessageModel lastMsg = this.Messages.Count > 0 ? this.Messages.Last() : null;
                    bool showSender = !(user.UserName == "GreenText" || user.UserName == "RedText");
                    FontStyle style;
                    FontWeight weight;
                    StaticMethods.ParseFontStyle(user.FontStyle, out style, out weight);

                    if (lastMsg != null && timestamp.Subtract(LastMessageReceivedTime).TotalSeconds < 10 && lastMsg.UserID == user.UserID)
                    {
                        lastMsg.IsLastInBatch = isLastInBatch;
                        this.Messages.Remove(lastMsg);
                        lastMsg.MessageText += Environment.NewLine + message;
                        this.Messages.Add(lastMsg);

                    }
                    else
                    {
                        this.Messages.Add(new MessageModel(user.UserID, timestamp)
                        {
                            NickName = user.PrettyName,
                            IsUserNameVisible = showSender,
                            MessageText = message,
                            FontWeight = weight,
                            FontStyle = style,
                            FontColor = new SolidColorBrush(StaticMethods.ColorFromHex(user.Color)),
                            IsLastInBatch = isLastInBatch
                        });
                    }

                    LastMessageReceivedTime = timestamp;
                }
            });
        }
        public override void Cleanup()
        {
            base.Cleanup();
        }
    }
}
